import joblib
import jieba
import re
from backend.nlp.text_preprocessor import TextPreprocessor
from backend.nlp.synonym_engine import SynonymEngine
from backend.nlp.entity_extractor import EntityExtractor
from backend.nlp.rule_engine import RuleEngine
from sklearn.feature_extraction.text import TfidfVectorizer
from backend.nlp.xunfei_api import XunfeiLLM
from backend.services.address_service import AddressService
from backend.services.order_service import OrderService
from backend.services.product_service import ProductService


class IntentRecognizer:
    def __init__(self, model_path='intent_model.pkl', vectorizer_path='tfidf_vectorizer.pkl'):
        # 初始化组件
        self.order_service = OrderService()
        self.address_service = AddressService()
        self.text_preprocessor = TextPreprocessor()
        self.synonym_engine = SynonymEngine()
        self.entity_extractor = EntityExtractor()
        self.rule_engine = RuleEngine()
        self.xunfei_api = XunfeiLLM()

        # 加载机器学习模型
        try:
            self.model = joblib.load(model_path)
            print(f"成功加载意图分类模型: {model_path}")
        except Exception as e:
            print(f"加载意图分类模型失败: {e}")
            self.model = None

        # 存储向量器路径
        self.vectorizer_path = vectorizer_path
        self.vectorizer = None

        # 停用词列表（应与训练时一致）
        self.STOP_WORDS = set(["的", "了", "和", "是", "就", "都", "而", "及", "与", "这", "那", "在", "要"])

    def recognize_intent(self, text, user_id=None, context=None):
        """
        识别用户输入的意图

        参数:
            text: 用户输入的文本
            user_id: 当前用户ID (可选)
            context: 对话上下文 (可选)

        返回:
            dict: 包含识别结果的字典
        """
        # 1. 文本清洗和标准化
        try:
            cleaned_text = self.text_preprocessor.clean_text(text)
            standardized_text = self.synonym_engine.replace_synonyms(cleaned_text)
            print(f"原始文本: {text} -> 标准化文本: {standardized_text}")
        except Exception as e:
            print(f"文本预处理失败: {e}")
            standardized_text = text

        # 2. 实体抽取
        try:
            entities = self.entity_extractor.extract_entities(standardized_text)
            print(f"抽取的实体: {entities}")
        except Exception as e:
            print(f"实体抽取失败: {e}")
            entities = {
                "product_id": None,
                "product_name": None,
                "order_id": None,
                "human_service": False,
                "price_query": False,
                "effect_query": False,
                "usage_query": False,
                "skin_type_query": False,
                "series_query": False,
                "after_sales": False,
                "address": False
            }

        # 3. 基于实体的意图判断（优先级从高到低）
        intent_type = None
        confidence = 0.95  # 基于规则的置信度

        # 3.1 人工服务请求（最高优先级）
        if entities["human_service"]:
            intent_type = "human_service"
            print("基于实体识别为: human_service (人工服务)")

        # 3.2 售后请求
        elif entities["after_sales"]:
            intent_type = "after_sales_query"
            print("基于实体识别为: after_sales_query (售后查询)")

        # 3.3 订单售后混合场景
        elif entities["order_id"] and (
                entities["after_sales"] or any(word in standardized_text for word in ["问题", "退货", "换货", "退款"])):
            intent_type = "after_sales_query"
            print("基于实体识别为: after_sales_query (售后查询)")

        # 3.4 地址修改
        elif entities["address"]:
            intent_type = "address_query"
            print("基于实体识别为: address_query (地址查询)")

        # 3.5 订单查询
        elif entities["order_id"]:
            intent_type = "order_query"
            print("基于实体识别为: order_query (订单查询)")

        # 3.6 产品相关意图细化
        elif entities["product_id"] or entities["product_name"]:
            if entities["price_query"]:
                intent_type = "product_query"
                print("基于实体识别为: product_query (产品查询-价格)")
            elif entities["effect_query"]:
                intent_type = "product_effect"
                print("基于实体识别为: product_effect (产品功效)")
            elif entities["usage_query"]:
                intent_type = "product_usage"
                print("基于实体识别为: product_usage (产品用法)")
            elif entities["skin_type_query"]:
                intent_type = "product_skin_type"
                print("基于实体识别为: product_skin_type (适用肤质)")
            elif entities["series_query"]:
                intent_type = "product_series"
                print("基于实体识别为: product_series (产品系列)")
            else:
                intent_type = "product_query"
                print("基于实体识别为: product_query (产品查询-默认)")

        # 4. 规则引擎（如果前面未识别出意图）
        if not intent_type:
            try:
                matched_intents = self.rule_engine.apply_rules(standardized_text, entities)
                print(f"规则引擎匹配结果: {matched_intents}")

                if matched_intents:
                    intent_type = matched_intents[0]["intent"]
                    confidence = matched_intents[0]["confidence"]
                    print(f"规则引擎识别为: {intent_type} (置信度: {confidence})")
            except Exception as e:
                print(f"规则引擎应用失败: {e}")

        # 5. 机器学习模型（如果前面未识别出意图）
        if not intent_type and self.model:
            try:
                # 预处理文本用于模型输入
                processed_text = self.preprocess_text(standardized_text)

                # 使用机器学习模型预测意图
                predicted_intent = self.model.predict([processed_text])[0]
                probabilities = self.model.predict_proba([processed_text])[0]
                confidence = max(probabilities)

                if confidence < 0.6:
                    intent_type = "unknown"
                    print(f"模型预测置信度过低 ({confidence:.2f})，标记为未知意图")
                else:
                    intent_type = predicted_intent
                    print(f"模型预测为: {intent_type} (置信度: {confidence:.2f})")
            except Exception as e:
                print(f"模型预测失败: {e}")
                intent_type = "unknown"
                confidence = 0.0

        # 6. 上下文处理（更新对话上下文）
        new_context = context.copy() if context else {}
        new_context.update({
            "last_intent": intent_type,
            "last_entities": entities,
            "last_text": standardized_text
        })

        # 处理多轮对话上下文
        if intent_type == "unknown" and "last_intent" in new_context:
            intent_type = new_context["last_intent"]
            confidence = 0.7
            print(f"继承上下文意图: {intent_type}")

        # 7. 返回识别结果
        return {
            "intent_type": intent_type,
            "entities": entities,
            "standardized_text": standardized_text,
            "confidence": confidence,
            "context": new_context
        }

    def preprocess_text(self, text):
        """为机器学习模型预处理文本"""
        # 加载预训练的向量器
        if not self.vectorizer:
            try:
                self.vectorizer = joblib.load(self.vectorizer_path)
                print(f"成功加载TF-IDF向量器: {self.vectorizer_path}")
            except Exception as e:
                print(f"加载向量器失败: {e}")
                # 创建简单的后备向量器
                self.vectorizer = TfidfVectorizer(max_features=1000)
                # 使用简单数据集拟合后备向量器
                self.vectorizer.fit(["产品", "订单", "售后", "地址", "人工"])
                print("创建并拟合后备向量器")

        # 使用与训练时相同的分词函数处理文本
        def custom_tokenizer(text):
            words = jieba.cut(text)
            return [word for word in words if word not in self.STOP_WORDS and len(word) > 1]

        # 使用向量器转换文本
        try:
            return self.vectorizer.transform([text])
        except Exception as e:
            print(f"文本向量化失败: {e}")
            # 返回空向量作为后备
            return self.vectorizer.transform([""])


    def handle_intent(self, intent_type, entities, text, user_id):
        """根据意图类型和实体生成响应"""
        # 公共产品服务实例

        product_service = ProductService()

        # 当有产品名称时查询详细信息
        if 'product_name' in entities:
            products = product_service.fuzzy_search_products(entities['product_name'])
            if products and len(products) > 0:
                # 获取第一个匹配产品的完整详情
                product_id = products[0]['product_id']
                product_details = product_service.get_product_details(product_id)

                if product_details:
                    return (f"产品信息：\n名称: {product_details['name']}\n"
                                f"价格: {product_details['price']}元\n"
                                f"系列: {product_details['series']}\n"
                                f"成分: {product_details['ingredients']}\n"
                                f"功效: {product_details['effect']}\n"
                                f"适用肤质: {product_details['skin_type']}\n"
                                f"使用方法: {product_details['usage_instructions']}")


        # 尝试从文本中提取产品信息（如果实体中缺失）
        if not entities.get("product_id") and not entities.get("product_name"):
            # 尝试从文本中提取产品ID
            product_id_match = re.search(r'[Pp]\d{3}', text)
            if product_id_match:
                entities["product_id"] = product_id_match.group().upper()

            # 尝试从文本中提取产品名称
            if not entities.get("product_id"):
                # 使用产品关键词进行模糊匹配
                product_keywords = {"净肌平衡", "特安修护", "多元优效", "乳液", "面霜", "精华", "面膜"}
                words = jieba.lcut(text)
                product_name_candidates = [word for word in words if word in product_keywords]

                if product_name_candidates:
                    candidates_text = " ".join(product_name_candidates)
                    products = product_service.fuzzy_search_products(candidates_text)
                    if products:
                        entities["product_name"] = products[0]["name"]

        if intent_type == "product_query":
            return self.handle_product_query(entities, text, user_id)
        elif intent_type == "order_query":
            return self.handle_order_query(entities, user_id, text)  # 添加 text 参数
        elif intent_type == "after_sales_query":
            return self.handle_after_sales_query(entities, user_id, text)  # 添加 text 参数

        elif intent_type == "address_query":
            return self.handle_address_query(entities, user_id, text)

        # 所有产品相关意图的统一处理
        elif intent_type in ["product_usage", "product_skin_type",
                             "product_series", "product_ingredients", "product_effect"]:
            return self.handle_product_attribute(intent_type, entities, user_id)

        elif intent_type == "human_service":
            return "正在为您转接人工客服，请稍候..."

        else:  # general_query 及其他
            return self.xunfei_api.get_answer([{"role": "user", "content": text}])

    # 新增统一的产品属性处理方法
    def handle_product_attribute(self, intent_type, entities, user_id):
        """处理产品属性查询（成分、用法、功效等）"""
        product_service = ProductService()
        product_id = entities.get("product_id")
        product_name = entities.get("product_name")

        # 优先使用产品ID查询
        if product_id:
            product = product_service.get_product_by_id(product_id)
            if product:
                return self.get_product_attribute_response(intent_type, product)
            return f"未找到ID为 {product_id} 的产品"

        # 使用产品名称查询
        if product_name:
            products = product_service.fuzzy_search_products(product_name)
            if products:
                # 如果只有一个匹配产品，直接返回
                if len(products) == 1:
                    return self.get_product_attribute_response(intent_type, products[0])

                # 多个匹配产品时列出选项
                product_list = "\n".join([f"{i + 1}. {p['name']}" for i, p in enumerate(products[:3])])
                return (f"找到多个匹配产品:\n{product_list}\n"
                        "请回复产品编号或提供更具体的产品名称/ID")

            return f"未找到名称为 '{product_name}' 的产品"

        # 无产品信息时提示
        return "请提供产品ID或名称，例如: 'P001的成分' 或 '净肌平衡清透水的用法'"

    def get_product_attribute_response(self, intent_type, product):
        """根据意图类型生成产品属性响应"""
        attribute_map = {
            "product_usage": ("使用方法", product.get("usage_instructions", "暂无使用方法信息")),
            "product_skin_type": ("适用肤质", product.get("skin_type", "暂无肤质信息")),
            "product_series": ("产品系列", product.get("series", "暂无系列信息")),
            "product_ingredients": ("主要成分", product.get("ingredients", "暂无成分信息")),
            "product_effect": ("产品功效", product.get("effect", "暂无功效信息")),
        }

        attribute_name, attribute_value = attribute_map.get(intent_type, ("信息", "暂无相关信息"))
        return f"{product['name']} 的{attribute_name}:\n{attribute_value}"

    # 重构产品查询处理方法
    def handle_product_query(self, entities, text, user_id):
        """处理产品查询意图"""
        product_service = ProductService()
        product_id = entities.get("product_id")
        product_name = entities.get("product_name")

        # 优先使用产品ID查询
        if product_id:
            product = product_service.get_product_by_id(product_id)
            if product:
                return self.format_product_response(product)
            return f"未找到ID为 {product_id} 的产品"

        # 使用产品名称查询
        if product_name:
            products = product_service.fuzzy_search_products(product_name)
            if products:
                # 如果只有一个匹配产品，直接返回详情
                if len(products) == 1:
                    return self.format_product_response(products[0])

                # 多个匹配产品时列出选项
                product_list = "\n".join([f"{i + 1}. {p['name']} - ¥{p['price']}" for i, p in enumerate(products[:3])])
                return (f"找到多个匹配产品:\n{product_list}\n"
                        "请回复产品编号或提供更具体的产品名称/ID")

            return f"未找到名称为 '{product_name}' 的产品"

        # 无产品信息时尝试从文本中提取
        return "请提供产品ID或名称，例如: 'P001' 或 '净肌平衡清透水'"

    def handle_order_query(self, entities, user_id, text):
        """处理订单查询意图"""
        order_service = OrderService()
        order_id = entities.get("order_id")

        # 尝试从文本中提取订单ID
        if not order_id:
            order_id_match = re.search(r'[Oo][Rr][Dd]\d{3}', text)
            if order_id_match:
                order_id = order_id_match.group().upper()

        if not order_id:
            return "请提供订单号，例如: '查询订单ORD123'"

        # 获取订单详情
        order_info = order_service.get_order_by_id(order_id, user_id)

        if not order_info:
            return f"未找到订单号为 {order_id} 的订单"

        # 格式化订单信息
        return (f"订单号: {order_info['order_id']}\n"
                f"产品: {order_info['product_name']}\n"
                f"状态: {order_info['status']}\n"
                f"下单时间: {order_info['order_time'].strftime('%Y-%m-%d %H:%M')}")

    def format_product_response(self, product):
        """格式化产品信息响应"""
        response = [
            f"产品名称: {product['name']}",
            f"价格: ¥{product['price']}",
            f"适用肤质: {product.get('skin_type', '暂无信息')}",
            f"产品系列: {product.get('series', '暂无信息')}"
        ]

        # 添加库存信息
        if "stock" in product:
            stock_status = "有货" if product["stock"] > 0 else "缺货"
            response.append(f"库存状态: {stock_status}")

        return "\n".join(response)

    def handle_after_sales_query(self, entities, user_id, text):  # 添加 text 参数
        """处理售后查询意图"""
        order_id = entities.get("order_id")

        # 尝试从文本中提取订单ID
        if not order_id:
            order_id_match = re.search(r'[Oo][Rr][Dd]\d{3}', text)  # 使用传入的 text 参数
            if order_id_match:
                order_id = order_id_match.group().upper()

        if not order_id:
            return "请提供订单号，例如: 'ORD123退货'"

        # 检查订单是否存在
        order_service = OrderService()
        order_info = order_service.get_order_by_id(order_id, user_id)

        if not order_info:
            return f"未找到订单号为 {order_id} 的订单"

        # 获取售后状态
        after_sales_status = order_info.get('after_sales_status', 'none')

        # 根据售后状态返回信息
        status_map = {
            'none': f"订单 {order_id} 尚未申请售后，如需申请自主上传并请说明原因",
            'applied': f"订单 {order_id} 售后申请已提交，正在审核中",
            'approved': f"订单 {order_id} 售后申请已通过，请按指引寄回商品",
            'rejected': f"订单 {order_id} 售后申请未通过，原因: {order_info.get('reject_reason', '未说明')}",
            'completed': f"订单 {order_id} 售后已完成"
        }

        return status_map.get(after_sales_status, f"订单 {order_id} 的售后状态未知")

    # 重构地址查询处理方法
    def handle_address_query(self, entities, user_id, text):
        """处理地址查询/修改意图"""
        order_id = entities.get("order_id")

        # 尝试从文本中提取订单ID
        if not order_id:
            order_id_match = re.search(r'[Oo][Rr][Dd]\d{3}', text)  # 使用传入的 text 参数
            if order_id_match:
                order_id = order_id_match.group().upper()

        if not order_id:
            return "请提供订单号，例如: 'ORD123修改地址'"

        # 检查订单是否存在
        order_service = OrderService()
        order_info = order_service.get_order_by_id(order_id, user_id)
        if not order_info:
            return f"未找到订单号为 {order_id} 的订单"

        address_service = AddressService()

        new_address = None
        if 'new_address' in entities:
            new_address = entities['new_address']  # 确保是字符串类型

        # 1. 既有订单号又有新地址：执行更新
        if entities.get('order_id') and new_address:
            success, msg = address_service.update_shipping_address(
                user_id,
                entities['order_id'],
                new_address
            )
            return msg

        # 2. 只有订单号：提示输入新地址
        elif entities.get('order_id'):
            orders = address_service.get_editable_orders(user_id)
            editable_ids = [order['order_id'] for order in orders]  # 正确迭代订单列表

            if entities['order_id'] in editable_ids:
                return f"订单{entities['order_id']}可以修改地址，请提供新的收货地址"
            else:
                return f"订单{entities['order_id']}不可修改地址（可能已发货或不存在）"

        # 3. 无订单号：展示可修改的订单列表
        else:
            editable_orders = address_service.get_editable_orders(user_id)
            if editable_orders:
                response = "您有以下可修改地址的订单（已付款未发货）：\n"
                for order in editable_orders:
                    response += (f"- 订单号: {order['order_id']}\n"
                                 f"  产品: {order['product_name']}\n"
                                 f"  当前地址: {order['shipping_address'][:20]}...\n\n")
                response += "请告诉我需要修改的订单号和新地址"
                return response
            else:
                return "您没有可修改地址的订单（只有已付款未发货的订单可以修改地址）"